import React, {
  useState,
  useCallback,
  useEffect,
  createElement,
  forwardRef,
  useImperativeHandle,
  useMemo,
  Fragment,
  ReactNode,
} from 'react';
import { Tabs, Modal, Button, Tag, Empty, Card } from 'antd';
import UserTab from './UserTab';
import UserGroupTab from './UserGroupTab';
import PositionTab from './PositionTab';
import DepartmentTab from './DepaertmentTab';
import { PREFIX, tabsData } from './utils/consts';
import { getMemberIconByKey } from './utils';
import classNames from 'classnames';
import { CloseCircleFilled } from '@ant-design/icons';
import { TextWidget, getMessage } from '@inbiz/react';
import { InbizIcon, useEvents } from '@inbiz/utils';
import { positionSelector } from './utils/operations';
import service from './service';
import './index.global.less';

const { TabPane } = Tabs;

const tabMap = {
  user: {
    comp: UserTab,
    lang: 'personTabs.user',
  },
  group: {
    comp: UserGroupTab,
    lang: 'personTabs.userGroup',
  },
  position: {
    comp: PositionTab,
    lang: 'personTabs.position',
  },
  department: {
    comp: DepartmentTab,
    lang: 'personTabs.department',
  },
};

interface ITagData {
  [x: string]: any;
  name: string;
  key: string;
}

interface ITag {
  [x: string]: any;
  data: ITagData;
  closable?: boolean;
  onClose?: (tag: ITagData) => void;
}

export const MemberSelectedTagView = ({ data, closable = true, onClose, ...tagProps }: ITag) => {
  return (
    <Tag
      icon={getMemberIconByKey(data.key.split('-')[0])}
      title={data.name}
      key={data.key}
      closable={closable}
      onClose={(e) => onClose?.(data)}
      closeIcon={<CloseCircleFilled />}
      className={classNames('inbiz-MemberSelectTag', tagProps.className)}
      {...tagProps}
    >
      {data.name}
    </Tag>
  );
};

export const MemberSelectedView = ({
  selected,
  height = 94,
  showEmpty,
  tagProps,
}: {
  selected: {
    [x: string]: any;
    name: string;
    key: string;
  }[];
  showEmpty: boolean;
  tagProps?: Omit<ITag, 'data'>;
  height?: number;
}) => {
  return (
    <Card className={classNames(`${PREFIX}-selectedOverlayContent`)} style={{ height: height }}>
      {selected.length ? (
        selected.map((tag) => {
          return <MemberSelectedTagView data={tag} {...tagProps} />;
        })
      ) : showEmpty ? (
        <Empty
          // 没有已选择的项
          description={getMessage('MemberSelect.lang.noItemsSelected')}
          imageStyle={{
            height: 48,
          }}
        />
      ) : null}
    </Card>
  );
};

const MemberSelect: React.ForwardRefRenderFunction<React.Ref<any>, TMemberSelect.IProps> = (
  props,
  ref: any,
) => {
  const { visible, config } = props;
  const {
    mode = 'normal',
    tabs,
    multiple = true,
    onOk,
    onCancel,
    hideTabBar = false,
    width = 800,
    pageSize = 10,
    departmentFilteringRules = 'selected',
    topDepartmentIds = [1],
    topPositionIds = [1],
    groupFilteringRules = 'selected',
    groupsIds = [],
    uniqueTabs = [],
    showType = 'modal',
    onRowClick,
    forbiddenItems,
    callBackEvents,
    emit,
    filterItems,
    collectivization,
  } = config || {};

  const [configEvents] = useEvents(callBackEvents, emit);
  const [currentTab, _currentTab] = useState<string>('');
  const [showSelected, _showSelected] = useState(false);
  const [selected, _selected] = useState<any[]>([]);
  const [selectedRowKeys, _selectedRowKeys] = useState([]);
  const [selectedMap, _selectedMap] = useState<Record<string, any>>({});
  const [okButtonLoading, setOkButtonLoading] = useState(false);

  const Wrapper = useMemo(() => (showType == 'modal' ? Modal : Fragment), [showType]);
  const WrapperElse = useMemo(
    () =>
      // showType == 'modal'
      //   ? Fragment
      //   : (props: { children?: ReactNode }) => <div className={PREFIX}>{props.children}</div>,
      (props: { children?: ReactNode }) =>
        <div className={PREFIX}>{props.children}</div>,
    [showType],
  );

  const _tabs = useMemo(() => {
    if (!tabs) {
      return tabsData;
    }
    if (tabs && tabs?.length == 0) {
      return tabsData;
    }
    if (typeof tabs?.[0] == 'string') {
      let __tabs = tabsData?.filter((item: any) => tabs?.includes(item?.memberKey));
      return __tabs;
    }
    return tabs?.filter((item: any) => !item?.hide);
  }, [tabs]);

  const setSelected = (sel: any) => {
    _selected(sel);
    _selectedRowKeys(sel.map((item: any) => item.key));
    const newSelectedMap = selectedMap;
    sel.map((item) => {
      if (!newSelectedMap[item.key]) {
        newSelectedMap[item.key] = item;
      }
    });
    _selectedMap(newSelectedMap);
    emit && emit('onSelect', sel);
  };

  useEffect(() => {
    _currentTab(_tabs[0]?.memberKey || '');
    let sel = config.selected || [];
    _selected(sel);
    _selectedRowKeys(sel.map((item: any) => item.key));
    const newSelectedMap = selectedMap;
    sel.map((item) => {
      if (!newSelectedMap[item.key]) {
        newSelectedMap[item.key] = item;
      }
    });
    _selectedMap(newSelectedMap);
  }, [visible]);

  const genSetSelected =
    (key: string) => (keys: any[], _data: any[] | undefined, _keyName?: string) => {
      const isUnique = uniqueTabs.indexOf(key as any) > -1;

      let keyName = 'key';
      let allKeys = [];
      let newKeys = [];
      let addonKeys = [],
        addonRows = [],
        delKeys = [];
      let data = _data;

      if (Array.isArray(data)) {
        allKeys = data.map((v) => v[keyName]);
        newKeys = [...selectedRowKeys];
        if (multiple) {
          if (keys.length) {
            let prevSelectedKeys = selectedRowKeys.filter((v) => v.startsWith(key));
            keys.map((k) => {
              if (!prevSelectedKeys.includes(k)) {
                addonKeys.push(k);
              }
            });
            prevSelectedKeys.map((k) => {
              if (allKeys.includes(k) && !keys.includes(k)) {
                delKeys.push(k);
              }
            });
            newKeys = newKeys.filter((k) => !delKeys.includes(k));
            newKeys = [...newKeys, ...addonKeys];
          } else {
            if (allKeys.length) {
              newKeys = newKeys.filter((k) => !allKeys.includes(k));
            } else {
              newKeys = newKeys.filter((k) => !key.startsWith(k));
            }
          }
        } else {
          newKeys = keys;
          addonKeys = keys;
          delKeys = [...selectedRowKeys];
        }
      } else {
        newKeys = [...selectedRowKeys];
        delKeys = selectedRowKeys.filter((key) => key.startsWith(key));
        addonKeys = keys.map((v) => v[keyName]);
        if (multiple) {
          if (keys.length) {
            newKeys = newKeys.filter((k) => !delKeys.includes(k));
            newKeys = [...newKeys, ...addonKeys];
          } else {
            newKeys = newKeys.filter((v) => !v.startsWith(key));
          }
        } else {
          newKeys = addonKeys;
        }
        data = keys;
      }

      let newSelectedMap = selectedMap;

      delKeys.map((k) => {
        delete newSelectedMap[k];
      });

      addonKeys.map((k) => {
        for (let item of data) {
          if (item[keyName] == k) {
            newSelectedMap[k] = item;
            break;
          }
        }
        if (newSelectedMap[k]) {
          addonRows.push(newSelectedMap[k]);
        }
      });

      let newSelected = newKeys
        .map((k) => {
          return newSelectedMap[k];
        })
        .filter((v) => !!v);

      let prevSelected = selected;
      let addonPaths = addonRows.map((v) => {
        const [type] = v.key.split('-');
        return [type, v.DeptPathName];
      });
      let toDeleteKeys: any[] = [];

      if (isUnique) {
        addonPaths.map(([type, pathName]) => {
          prevSelected.map((item) => {
            const [curType] = item.key.split('-');
            if (type == curType && pathName && item.DeptPathName) {
              if (
                item.DeptPathName.indexOf(pathName) > -1 ||
                pathName.indexOf(item.DeptPathName) > -1
              ) {
                toDeleteKeys.push(item.key);
              }
            }
          });
        });
      }

      let cacheNewSelected = [...newSelected];
      newSelected = cacheNewSelected.filter((item) => {
        return !toDeleteKeys.includes(item.key);
      });

      _selectedMap(newSelectedMap);
      setSelected(newSelected);
    };

  const selectCardHeight = 94;
  const tabHeight = showType == 'modal' ? (showSelected ? 427 - selectCardHeight : 427) : '100%';

  const handleOk = () => {
    let _selected = selected;
    let _users = selected?.filter((item: any) => item?.key?.startsWith('user'));
    if (
      _users &&
      _users?.length > 0 &&
      !_tabs?.find((item: any) => item?.memberKey == 'user')?.positionSelect &&
      _tabs?.find((item: any) => item?.memberKey == 'user')?.departmentDisplayFormat == 'positionName' &&
      _users?.filter((item: any) => item?.usertype == 'department')?.length > 0
    ) {
      // 从部门选的人员获取主职位id
      let __users = _users?.filter((item: any) => item?.usertype == 'department');
      setOkButtonLoading(true);
      Promise.all(__users?.map((user: any) => service.getPositionListByKetword(user?.mainpositionname))).then((res: any) => {
        res?.map((item: any, index: number) => {
          let _positions = item?.data;
          let _position = _positions?.find((item1: any) => item1?.Name == __users[index]?.mainpositionname);
          __users[index].positionid = _position?.ID;
        });
        onOk(selectedRowKeys, _selected, selectedMap);
        setOkButtonLoading(false);
      }).catch((error) => {
        setOkButtonLoading(false);
      });
    } else if (
      _users &&
      _users?.length > 0 &&
      _tabs?.find((item: any) => item?.memberKey == 'user')?.positionSelect
    ) {
      //需要选择职位
      positionSelector({
        users: _users,
        onOk: (res: any) => {
          let _selected = selected?.map((item: any) => {
            if (item?.key?.startsWith('user') && res[item?.key]) {
              return {
                ...item,
                selectedposition: res[item?.key],
              };
            } else {
              return item;
            }
          });
          if (
            _tabs?.find((item: any) => item?.memberKey == 'user')?.departmentDisplayFormat == 'positionName' && _users?.filter((item: any) => item?.usertype == 'department')?.length > 0
            ||
            _tabs?.find((item: any) => item?.memberKey == 'user')?.userGroupDisplayFormat == 'positionName' && _users?.filter((item: any) => item?.usertype == 'userGroup')?.length > 0
            ) {
            let _users = _selected?.filter((item: any) => item?.key?.startsWith('user'));
            let __users = _users?.filter((item: any) => item?.usertype == 'department');
            let ___users = _users?.filter((item: any) => item?.usertype == 'userGroup');
            let users = __users?.concat(___users);
            setOkButtonLoading(true);
            Promise.all(users?.map((user: any) => service.getPositionListByKetword(user?.selectedposition))).then((res: any) => {
              res?.map((item: any, index: number) => {
                let _positions = item?.data;
                let __position = _positions?.find((item1: any) => item1?.Name == users[index]?.selectedposition);
                users[index]['positionid'] = __position?.ID;
              })
              onOk(selectedRowKeys, _selected, selectedMap);
              setOkButtonLoading(false);
            }).catch((error) => {
              setOkButtonLoading(false);
            });
          } else {
            onOk(selectedRowKeys, _selected, selectedMap);
          }
        },
      });
    } else {
      onOk(selectedRowKeys, selected, selectedMap);
    }
  };

  const tabProps = useCallback(
    (key: MemberTabKey) => ({
      uniqueTabs: uniqueTabs && uniqueTabs.length,
      isUnique: uniqueTabs.map((item: any) => item?.memberKey).indexOf(key as any) > -1,
      mode,
      departmentFilteringRules,
      topDepartmentIds,
      topPositionIds,
      groupFilteringRules,
      groupsIds,
      pageSize: pageSize,
      height: tabHeight,
      tabKey: key,
      multiple,
      allSelected: selected,
      allSelectedRowKeys: selectedRowKeys,
      selectedRowKeys: selectedRowKeys.filter((item: any) => {
        return item.startsWith(key);
      }),
      selected: selected.filter((item: any) => {
        return item.key.startsWith(key);
      }),
      setSelected: genSetSelected(key),
      onRowClick: (data: Record<string, any>, index: number) => onRowClick?.(data, index, key),
      forbiddenItems: forbiddenItems?.[key] || [],
      filterItems: filterItems?.[key] || [],
      collectivization: collectivization,
      tab: _tabs?.find((item: any) => item?.memberKey == key),
      configEvents,
    }),
    [
      uniqueTabs,
      selected,
      selectedRowKeys,
      showSelected,
      tabHeight,
      genSetSelected,
      collectivization,
      configEvents,
    ],
  );

  useImperativeHandle(
    ref,
    () => {
      return {
        selected,
        selectedRowKeys,
        selectedMap,
      };
    },
    [selected, selectedRowKeys, selectedMap],
  );

  return (
    <Wrapper
      destroyOnClose
      visible={visible}
      onOk={onOk}
      onCancel={onCancel}
      wrapClassName={PREFIX}
      width={width}
      title={
        props.modalTitle ? (
          <TextWidget>{props.modalTitle}</TextWidget>
        ) : uniqueTabs && uniqueTabs.length ? (
          getMessage('MemberSelect.lang.topLevelDepartSelection')
        ) : (
          getMessage('MemberSelect.lang.memberSelect')
        )
      }
      footer={
        <div className={`${PREFIX}-modalFooter`}>
          <div className={`${PREFIX}-modalFooterContent`}>
            <div className={`${PREFIX}-modalFooterLeft`}>
              <label
                className={`${PREFIX}-selectedCountBtn`}
                onClick={(e) => _showSelected(!showSelected)}
              >
                <TextWidget>MemberSelect.lang.selectedCount</TextWidget>
                <span className={`${PREFIX}-primaryText`}> {selected.length} </span>
                {showSelected ? (
                  <InbizIcon
                    type="icon-ic-arrow-up-bold"
                    style={{ marginLeft: 5, fontSize: 12, color: 'var(--inbiz-color-primary)' }}
                  />
                ) : (
                  <InbizIcon
                    type="icon-ic-arrow-down-bold"
                    style={{
                      marginLeft: 5,
                      fontSize: 12,
                      color: 'var(--inbiz-color-heading)',
                      fontWeight: 'bold',
                    }}
                  />
                )}
              </label>
            </div>
            <Button onClick={onCancel}>
              <span>
                <TextWidget>MemberSelect.lang.action.cancel</TextWidget>
              </span>
            </Button>
            <Button type="primary" onClick={handleOk} loading={okButtonLoading}>
              <span>
                <TextWidget>MemberSelect.lang.action.ok</TextWidget>
              </span>
            </Button>
          </div>
        </div>
      }
    >
      <WrapperElse>
        {uniqueTabs && uniqueTabs.length ? (
          _tabs.map((name) => {
            const item = tabMap[name?.memberKey];
            return createElement(item.comp, tabProps(name?.memberKey));
          })
        ) : _tabs.length > 1 ? (
          <Tabs
            onChange={_currentTab}
            activeKey={currentTab}
            className={`${PREFIX}-tabs ${hideTabBar ? PREFIX + '-hideTabBar' : ''}`}
          >
            {_tabs.map((name) => {
              const item = tabMap[name?.memberKey];
              if (!item) {
                return null;
              }
              return (
                <TabPane
                  style={{
                    height: tabHeight,
                  }}
                  key={name?.memberKey}
                  tab={getMessage(name?.title)}
                >
                  {createElement(item.comp, tabProps(name?.memberKey))}
                </TabPane>
              );
            })}
          </Tabs>
        ) : (
          <div
            style={{
              height: tabHeight,
            }}
          >
            {createElement(tabMap[_tabs[0]?.memberKey]?.comp, tabProps(_tabs[0]?.memberKey))}
          </div>
        )}
        {showSelected ? (
          <MemberSelectedView
            selected={selected}
            height={selectCardHeight}
            showEmpty={false}
            tagProps={{
              onClose: (tag) => {
                setSelected(selected.filter((v) => v.key != tag.key));
              },
            }}
          />
        ) : null}
      </WrapperElse>
    </Wrapper>
  );
};

export default forwardRef(MemberSelect);
